package com.seguriapp.services;

import static com.google.common.collect.Lists.newArrayList;

import java.util.Collections;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.seguriapp.dao.DistrictDao;
import com.seguriapp.dao.EntityDao;
import com.seguriapp.dao.EntityTypeDao;
import com.seguriapp.dao.UserDao;
import com.seguriapp.entities.District;
import com.seguriapp.entities.SeguriAppEntity;
import com.seguriapp.entities.SeguriAppEntityType;
import com.seguriapp.util.SearchFilterEntity;
import com.seguriapp.util.Util;

/**
 * SeguriAppEntity Service Implementation
 * 
 * @author Tania Gonzales (taniadgv@gmail.com)
 */
@Service
public class EntityServiceImpl implements EntityService {

  @Autowired
  private EntityDao entityDao;

  @Autowired
  private EntityTypeDao entityTypeDao;

  @Autowired
  private UserDao userDao;

  @Autowired
  private DistrictDao districtDao;

  public void setEntityDao(final EntityDao entityDao) {
    this.entityDao = entityDao;
  }

  public void setEntityTypeDao(final EntityTypeDao entityTypeDao) {
    this.entityTypeDao = entityTypeDao;
  }

  @Transactional
  public void saveEntity(final SeguriAppEntity entidad) {
    entityDao.save(entidad);
  }

  @Transactional
  public List<SeguriAppEntity> listEntities() {
    return entityDao.list();
  }

  @Transactional
  public void deleteEntity(final SeguriAppEntity entidad) {
    entityDao.delete(entidad);
  }

  @Transactional
  public List<SeguriAppEntity> listEntitiesByUbication(final double latitude, final double longitude, final double radio) {
    return entityDao.listEntitiesByUbication(latitude, longitude, radio);
  }

  @Transactional
  public List<SeguriAppEntity> listEntitiesByCategories(final List<Long> categoriesIdsList, final Long userId) {
    if (categoriesIdsList == null) {
      return entityDao.list();
    }
    if (userId != null && !isAdmin(userId)) {
      return entityDao.listEntitiesByCategories(categoriesIdsList, userId);
    } else {
      return entityDao.listEntitiesByCategories(categoriesIdsList);
    }
  }

  @Transactional
  public List<SeguriAppEntity> listEntitiesByCategories(final List<Long> categoriesIdsList, double latitude, double longitude) {
    List<SeguriAppEntity> entitiesList = newArrayList();
    if (categoriesIdsList == null) {
      entitiesList = entityDao.list();
    }
    entitiesList = entityDao.listEntitiesByCategories(categoriesIdsList);
    // order list by distance given the latitude and longitude
    for (final SeguriAppEntity seguriAppEntity : entitiesList) {
      seguriAppEntity.setDistance(Util.distance(seguriAppEntity.getLatitude(), seguriAppEntity.getLongitude(), latitude, longitude, 'K'));
    }
    Collections.sort(entitiesList);
    return entitiesList;
  }

  @Transactional
  public List<SeguriAppEntityType> getSeguriAppEntityTypeList() {
    return entityTypeDao.list();
  }

  @Transactional
  public List<District> getDistrictsList(final Long provinceId) {
    return districtDao.getDistrictsList(provinceId);
  }

  @Transactional
  public List<SeguriAppEntity> listEntities(final SearchFilterEntity searchFilter) {
    return entityDao.listEntities(searchFilter);
  }

  @Transactional
  public long getEntitiesTotalPages(final SearchFilterEntity searchFilter) {
    return entityDao.getEntitiesTotalPages(searchFilter);
  }

  private boolean isAdmin(final Long userId) {
    return userDao.isUserAdmin(userId);
  }
}
